#include "common.h"
#include <QDebug>
#include <QKeySequence>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include <QMap>
#include <QX11Info>

#define XK_MISCELLANY
#define XK_LATIN1
#define XK_KOREAN
#define XK_XKB_KEYS
#include <X11/keysymdef.h>

const QMap<QString, int> Platform::getKeyMap()
{
    Display* display = XOpenDisplay(nullptr);
    if (display == nullptr)
    {
        fprintf(stderr, "xdotool: fail to open display\n");
    }
    QMap<QString, int> keyMap;
    for (unsigned char i = 0; i < 100; i++)
    {
        QString keyName(XKeysymToString(XkbKeycodeToKeysym(display, i, 0, 0)));
        if (!keyName.isEmpty())
        {
            keyMap[keyName] = i;
        }
    }
    if (display != nullptr)
    {
        XCloseDisplay(display);
    }
    keyMap["Control"] = keyMap["Control_L"];
    keyMap["ctrl"] = keyMap["Control_L"];
    keyMap["alt"] = keyMap["Alt_L"];
    keyMap["super"] = keyMap["Super_L"];
    keyMap["shift"] = keyMap["Shift_L"];
    return keyMap;
}


static const unsigned int KeyTbl[] = {

    // misc keys

    XK_Escape,                  Qt::Key_Escape,
    XK_Tab,                     Qt::Key_Tab,
    XK_ISO_Left_Tab,            Qt::Key_Backtab,
    XK_BackSpace,               Qt::Key_Backspace,
    XK_Return,                  Qt::Key_Return,
    XK_Insert,                  Qt::Key_Insert,
    XK_Delete,                  Qt::Key_Delete,
    XK_Clear,                   Qt::Key_Delete,
    XK_Pause,                   Qt::Key_Pause,
    XK_Print,                   Qt::Key_Print,
    0x1005FF60,                 Qt::Key_SysReq,         // hardcoded Sun SysReq
    0x1007ff00,                 Qt::Key_SysReq,         // hardcoded X386 SysReq

    // cursor movement

    XK_Home,                    Qt::Key_Home,
    XK_End,                     Qt::Key_End,
    XK_Left,                    Qt::Key_Left,
    XK_Up,                      Qt::Key_Up,
    XK_Right,                   Qt::Key_Right,
    XK_Down,                    Qt::Key_Down,
    XK_Prior,                   Qt::Key_PageUp,
    XK_Next,                    Qt::Key_PageDown,

    // modifiers

    XK_Shift_L,                 Qt::Key_Shift,
    XK_Shift_R,                 Qt::Key_Shift,
    XK_Shift_Lock,              Qt::Key_Shift,
    XK_Control_L,               Qt::Key_Control,
    XK_Control_R,               Qt::Key_Control,
    XK_Meta_L,                  Qt::Key_Meta,
    XK_Meta_R,                  Qt::Key_Meta,
    XK_Alt_L,                   Qt::Key_Alt,
    XK_Alt_R,                   Qt::Key_Alt,
    XK_Caps_Lock,               Qt::Key_CapsLock,
    XK_Num_Lock,                Qt::Key_NumLock,
    XK_Scroll_Lock,             Qt::Key_ScrollLock,
    XK_Super_L,                 Qt::Key_Super_L,
    XK_Super_R,                 Qt::Key_Super_R,
    XK_Menu,                    Qt::Key_Menu,
    XK_Hyper_L,                 Qt::Key_Hyper_L,
    XK_Hyper_R,                 Qt::Key_Hyper_R,
    XK_Help,                    Qt::Key_Help,
    0x1000FF74,                 Qt::Key_Backtab,        // hardcoded HP backtab
    0x1005FF10,                 Qt::Key_F11,            // hardcoded Sun F36 (labeled F11)
    0x1005FF11,                 Qt::Key_F12,            // hardcoded Sun F37 (labeled F12)

    0,                          0
};

Qt::Key Platform::toQtKey(unsigned char nativeCode)
{
    KeySym sym = XkbKeycodeToKeysym(QX11Info::display(), nativeCode, 0, 0);
    QString keyName(XKeysymToString(sym));
    Qt::Key key = Qt::Key(QKeySequence::fromString(keyName)[0]);
    if (key == Qt::Key_unknown)
    {
        for (int i = 0; KeyTbl[i] != 0; i += 2)
        {
              if (KeyTbl[i] == sym)
                  key = Qt::Key(KeyTbl[i+1]);
        }
    }
    return key;

}
